package src;

import java.util.LinkedList;
import java.util.ListIterator;
import java.util.NoSuchElementException;

/**
 * 
 * @author Patrik Mihalcin
 */
public class Logic {

	private LinkedList<Double> truthDegrees = new LinkedList<Double>();
	private Integer logicDegree = 2;

	public Logic(Integer logicDegree) {
		this.logicDegree = logicDegree;
		
		Double diff = 1.0 / (logicDegree - 1);
		diff = round(diff, 2);
		
		Double value = round(1.0, 2);
		
		for (int i = 0; i < logicDegree - 1; i++) {
			this.truthDegrees.add(value);
			
			value = value - diff;
			value = round(value, 2);
		}
		
		this.truthDegrees.add(round(0.0, 2));
	}
	
	private Double round(Double number, Integer precision) {
		if (precision <= 0) {
			return null;
		}
		StringBuilder s = new StringBuilder("1");
		for (int i = 0; i < precision; i++) {
			s.append("0");
		}
		precision = Integer.parseInt(s.toString());
		return (double)Math.round(number * precision) / precision;
	}

	public Double implication(Double a, Double b) { 
//		fuzzy implikacia - reziduum
		return Math.min(1.0 - a + b, 1.0);
	}
	
	public Double infimum(Double a, Double b) {
		return Math.min(a, b);
	}

	public Double disjunction(Double a, Double b) {
		return implication(implication(a, 0.0), b);
	}
	
	public Double strongConjunction(Double a, Double b) { 
//		fuzzy konjunkcia
		return Math.max(0.0, a + b - 1.0);
	}
	
//	private Double supremum(Double a, Double b) {
//		return Math.max(a, b);
//	}
//
//	private Double ekvivalencia(Double a, Double b) { 
////		bireziduum
////		return 1.0 - Math.abs(a - b);
//		return Math.min(implikacia(a, b), implikacia(b, a));
//	}

	public Double getNextTruthValue(Double truthValue) { 
		if (truthValue >= this.truthDegrees.getFirst()) {
			throw new NoSuchElementException("Truth value " + truthValue + " does not have successor.");
		}
		
		Double vysledok = null;
		for (ListIterator<Double> it = truthDegrees.listIterator(truthDegrees.size()); it.hasPrevious();) {
//			prechadzame truthDegrees zozadu
			if (it.previous().equals(round(truthValue, 2))) {
				vysledok = it.previous();
			}
		}
		return vysledok;
	}

	public LinkedList<Double> getTruthDegrees() {
		return truthDegrees;
	}
	
	public Integer getLogicDegree() {
		return logicDegree;
	}
}